#
# This file is part of LiteX-Boards.
#
# Copyright (c) 2021 Lucas Teske <lucas@teske.com.br>
# SPDX-License-Identifier: BSD-2-Clause

# The Muselab IceSugar Pro PCB and IOs have been documented by @wuxx
# https://github.com/wuxx/icesugar-pro

from litex.build.generic_platform import *
from litex.build.lattice import LatticeECP5Platform
from litex.build.lattice.programmer import EcpDapProgrammer

# IOs ----------------------------------------------------------------------------------------------

_io = [
    # Clk
    ("clk25", 0, Pins("B3"), IOStandard("LVCMOS33")),

    # Reset button
    ("cpu_reset_n", 0, Pins("C26"), IOStandard("LVCMOS33"), Misc("PULLMODE=UP")),

    # Led
    ("user_led_n", 0, Pins("D26"), IOStandard("LVCMOS33")), # Red
    ("user_led_n", 1, Pins("A28"), IOStandard("LVCMOS33")), # Green
    ("user_led_n", 2, Pins("A29"), IOStandard("LVCMOS33")), # Blue

    ("pwmled", 0,
        Subsignal("r", Pins("A30")),
        Subsignal("g", Pins("Y32")),
        Subsignal("b", Pins("W31")),
        IOStandard("LVCMOS33"),
    ),

    # Switches / jumper-attached to PMOD4
    ("user_sw", 0, Pins("AG30"), IOStandard("LVCMOS33")),
    ("user_sw", 1, Pins("AK29"), IOStandard("LVCMOS33")),
    ("user_sw", 2, Pins("AH32"), IOStandard("LVCMOS33")),
    ("user_sw", 3, Pins("AH28"), IOStandard("LVCMOS33")),

    # Serial
    ("serial", 0, # iCELink
        Subsignal("tx", Pins("AM28")),
        Subsignal("rx", Pins("AL28")),
        IOStandard("LVCMOS33")
    ),

    # IrDA  
    ("irda", 0, # IrDA sir mode
        Subsignal("tx", Pins("C11")),
        Subsignal("rx", Pins("C12")),
        IOStandard("LVCMOS33")
    ),

    # ONEWIRE
    ("onewire", 0,
        Subsignal("dqwire", Pins("A3"), Misc("PULLMODE=UP")),
        IOStandard("LVCMOS33")
    ),

    # RTC XTAL 32768Hz
    ("rtc", 0, 
        Subsignal("xtali", Pins("D6")),
        Subsignal("xtalo", Pins("D7")),
        IOStandard("LVCMOS33")
    ),

    # CAN-FD
    ("can", 0, # CAN bus
        Subsignal("tx", Pins("T3")),
        Subsignal("rx", Pins("T4")),
        IOStandard("LVCMOS33")
    ),

    # I2S-controller
    ("mi2s", 0,
        Subsignal("tx",    Pins("K3")),
        #Subsignal("rx",    Pins("H3")),
        Subsignal("clk",   Pins("J3")),
        Subsignal("sync",  Pins("J2")),
        IOStandard("LVCMOS33")
    ),

    # I2S-peripheral
    ("si2s", 0,
        #Subsignal("tx",    Pins("K3")),
        Subsignal("rx",    Pins("H3")),
        Subsignal("clk",   Pins("J3")),
        Subsignal("sync",  Pins("J2")),
        IOStandard("LVCMOS33")
    ),

    # SPIFlash (W25Q256JV (32MB))
    ("spiflash", 0,
        Subsignal("cs_n", Pins("AJ3")),
        # https://github.com/m-labs/nmigen-boards/pull/38
        #Subsignal("clk",  Pins("")), driven through USRMCLK
        Subsignal("mosi", Pins("AK2")),
        Subsignal("miso", Pins("AJ2")),
        IOStandard("LVCMOS33"),
    ),

    # SDRAM (IS42S16160B (32MB))
    ("sdram_clock", 0, Pins("E25"), IOStandard("LVCMOS33")),
    ("sdram", 0,
        Subsignal("a", Pins(
            "E30 F28 C32 E29 F32 D30 E32 D29",
            "D32 C31 H32 F31 F29")),
        Subsignal("dq", Pins(
            " V26 R27 V27 T26 U28 T27 T29 U26",
            " P27 K28 P26 L26 K27 N26 L29 K26")),
        Subsignal("we_n",  Pins("J32")),
        Subsignal("ras_n", Pins("K31")),
        Subsignal("cas_n", Pins("K30")),
        Subsignal("cs_n", Pins("K29")),
        Subsignal("cke",  Pins("K32")),
        Subsignal("ba",    Pins("H31 H30")),
        Subsignal("dm",   Pins("R26 L27")),
        IOStandard("LVCMOS33"),
        Misc("SLEWRATE=FAST")
    ),

    # SDCard
    ("spisdcard", 0,
        Subsignal("clk",  Pins("AK3")),
        Subsignal("mosi", Pins("AH3"), Misc("PULLMODE=UP")),
        Subsignal("cs_n", Pins("AK1"), Misc("PULLMODE=UP")),
        Subsignal("miso", Pins("AG1"), Misc("PULLMODE=UP")),
        Misc("SLEWRATE=FAST"),
        IOStandard("LVCMOS33"),
    ),
    ("sdcard", 0,
        Subsignal("clk", Pins("AK3")),
        Subsignal("cmd", Pins("AH3"), Misc("PULLMODE=UP")),
        Subsignal("data", Pins("AG1 AJ1 AH1 AK1"), Misc("PULLMODE=UP")),
        Misc("SLEWRATE=FAST"),
        IOStandard("LVCMOS33")
     ),

    # SPI
    ("spi", 0,
        Subsignal("clk",  Pins("AE31")),
        Subsignal("cs_n", Pins("AE32"), Misc("PULLMODE=UP")),
        Subsignal("mosi", Pins("AD32"), Misc("PULLMODE=UP")),
        Subsignal("miso", Pins("AC32"), Misc("PULLMODE=UP")),
        Misc("SLEWRATE=FAST"),
        IOStandard("LVCMOS33"),
    ),

    # I2C bitbang
    ("i2c", 0,
        Subsignal("scl", Pins("AB32"), Misc("PULLMODE=UP")),
        Subsignal("sda", Pins("AB31"), Misc("PULLMODE=UP")),
        IOStandard("LVCMOS33")
    ),

    # IIC from opencores.org
    ("iic", 0,
        Subsignal("scl", Pins("AC31"), Misc("PULLMODE=UP")),
        Subsignal("sda", Pins("AC30"), Misc("PULLMODE=UP")),
        IOStandard("LVCMOS33")
    ),

    # I2C from litei2c
    ("i2cmaster", 0,
        Subsignal("scl", Pins("A16"), Misc("PULLMODE=UP")),
        Subsignal("sda", Pins("D15"), Misc("PULLMODE=UP")),
        IOStandard("LVCMOS33")
    ),

    # USB HOST
    ("usb_host", 0,
        Subsignal("dp", Pins("A2")),
        Subsignal("dm", Pins("B1")),
        IOStandard("LVCMOS33")
    ),

    # USB ACM SLAVE
    ("usb", 0,
        Subsignal("d_p", Pins("A6")),
        Subsignal("d_n", Pins("A7")),
        Subsignal("pullup", Pins("A8")),
        IOStandard("LVCMOS33")
    ),

    # JTAG.
    ("jtag", 0,
        Subsignal("tck", Pins("F13")),
        Subsignal("tms", Pins("J13")),
        Subsignal("tdi", Pins("G13")),
        Subsignal("tdo", Pins("H13")),
        IOStandard("LVCMOS33"),
    ),

    # Sata
    ("sata", 0,
        Subsignal("rx_p", Pins("A8")),
        Subsignal("rx_n", Pins("A7")),
        Subsignal("tx_p", Pins("B8")),
        Subsignal("tx_n", Pins("B7")),
    ),


    # GPDI
    ("gpdi", 0,
        Subsignal("clk_p",   Pins("E2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("clk_n",   Pins("D3"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data0_p", Pins("G1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data0_n", Pins("F1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data1_p", Pins("J1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data1_n", Pins("H2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data2_p", Pins("L1"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
        Subsignal("data2_n", Pins("K2"), IOStandard("LVCMOS33"), Misc("DRIVE=4")),
    ),

    # RMII Ethernet PHY (WaveShare Board)
    # Assumed to be modified to be PMOD-compatible (TX1 tied to MDIO)
    # Position is P4 header "top half" (toward the GPDI connector)
    ("eth_clocks", 0,
        Subsignal("ref_clk", Pins("A15")),
        IOStandard("LVCMOS33"),
    ),
    ("eth", 0,
        Subsignal("rx_data", Pins("C16 B16")),
        Subsignal("crs_dv",  Pins("B14")),
        Subsignal("tx_en",   Pins("F16")),
        Subsignal("tx_data", Pins("A14 F15")),
        Subsignal("mdc",     Pins("C15")),
        Subsignal("mdio",    Pins("C14")),
        IOStandard("LVCMOS33"),
    ),

]

# from colorlight_i5.py adapted to icesugar pro
# https://github.com/wuxx/icesugar-pro/blob/master/doc/iCESugar-pro-pinmap.png
_connectors = [
    ("pmode", "N3  M2  L2  G2  P1  N1  M1  K1"),
    ("pmodf", "T6  R5  R4  R3  P7  R6  T4  T3"),
]

# Platform -----------------------------------------------------------------------------------------

class Platform(LatticeECP5Platform):
    default_clk_name   = "clk25"
    default_clk_period = 1e9/25e6

    def __init__(self, toolchain="trellis"):
        device     = "LFE5UM5G-85F-8BG756C"
        io         = _io
        connectors = _connectors
        LatticeECP5Platform.__init__(self, device, io, connectors=connectors, toolchain=toolchain)

    def create_programmer(self):
        return EcpDapProgrammer()

    def do_finalize(self, fragment):
        LatticeECP5Platform.do_finalize(self, fragment)
        self.add_period_constraint(self.lookup_request("clk25", loose=True), 1e9/25e6)
